#include <iostream>
#include <string>
#include <stdexcept>
#include <exception>
#include <vector>
#include "SDL.h"
#include "SDL_image.h"
#include "sdlmap.h"
#include "sdlbutton.h"
#include "sdltext.h"
#include "character.h"
#include "item.h"
#include "inventorywindow.h"
using namespace std;

InventoryWindow::InventoryWindow(class Character *character) throw(inventory_error)
{
       visible_ = false;
       winBackground_ = NULL;
       closeButton_ = NULL;
       closeText_ = NULL;
       titleText_ = NULL;
       highlight_ = NULL;
       window_ = NULL;
       item_ = NULL;
       rightHandClicked = false;
       leftHandClicked = false;


       window_ = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, 332, 401, 32, 0, 0, 0, 0);
       winRect_.h = window_->h;
       winRect_.w = window_->w;
       winRect_.x = 346;
       winRect_.y = 104;
       winBackground_ = IMG_Load("adventure2/graphics/backdrops/inventorybackground.png");
       if(winBackground_ == NULL)
       {
	      throw inventory_error("Could not load adventure2/graphics/backdrops/inventorybackground.png");
       }

       winBRect_.x = 0;
       winBRect_.y = 0;
       winBRect_.w = winBackground_->w;
       winBRect_.h = winBackground_->h;

       highlight_ = IMG_Load("adventure2/graphics/backdrops/inventoryhighlight.png");
       if(highlight_ == NULL)
       {
	      throw inventory_error("Could not load adventure2/graphics/backdrops/inventoryhighlight.png");
       }
       lightRect_.w = highlight_->w;
       lightRect_.h = highlight_->h;

       try
       {
	      closeText_ = new SDLText(255, 255, 255, 20, "CHECKBK0.TTF", "x");
	      titleText_ = new SDLText(3, 3, 255, 255, 255, 20, "CHECKBK0.TTF", "Inventory");
	      closeButton_ = new SDLButton("uclose_inventory.png", "cclose_inventory.png", 308, 0, winBackground_, closeText_);
       }
       catch(sdltext_error &error)
       {
	      cout << error.what() << endl;
	      abort();
       }
       catch(sdlbutton_error &error)
       {
	      cout << error.what() << endl;
	      abort();
       }

       character_ = character;
}

InventoryWindow::~InventoryWindow()
{
       SDL_FreeSurface(winBackground_);
       SDL_FreeSurface(highlight_);
       SDL_FreeSurface(item_);
       SDL_FreeSurface(window_);

       delete closeText_;
       delete titleText_;
       delete closeButton_;
}

void InventoryWindow::render(SDL_Surface *screen)
{
       if(visible_ == true)
       {
	      SDL_BlitSurface(winBackground_, NULL, window_, &winBRect_);
	      // Render a highlightbox if right hand is clicked.
	      if(rightHandClicked)
	      {
		     lightRect_.x = 241;
		     lightRect_.y = 82;
		     SDL_BlitSurface(highlight_, NULL, window_, &lightRect_);
	      }

	      // Render a highlight box if left hand is clicked.
	      if(leftHandClicked)
	      {
		     lightRect_.x = 29;
		     lightRect_.y = 82;
		     SDL_BlitSurface(highlight_, NULL, window_, &lightRect_);
	      }

	      drawItems();
	      closeButton_->render();
	      titleText_->render(window_);
	      SDL_BlitSurface(window_, NULL, screen, &winRect_);
       }
}

void InventoryWindow::hide()
{
       visible_ = false;
}

void InventoryWindow::show()
{
       visible_ = true;
}

bool InventoryWindow::is_clicked(int x, int y, bool &visible, SDLMap *map)
{
       int itemNumber = -1;
       // Subtract position of window on screen to make it relative
       x -= 346;
       y -= 104;

       if(closeButton_->is_clicked(x, y) == true)
       {
	      this->hide();
	      visible = false;
       }

       // Check if area of items is clicked
       if(x >= 6 && x <= 326)
       {
	      if(y >= 269 && y <= 397)
	      {
		     // If user has equiped left or right hand
		     // and there is room in the inventory the item
		     // will be placed there.
		     if(leftHandClicked && character_->getLeftHand() != 0)
		     {
			    character_->add(character_->removeLeftHandItem());
			    leftHandClicked = false;
		     }

		     if(rightHandClicked && character_->getRightHand() != 0)
		     {
			    character_->add(character_->removeRightHandItem());
			    rightHandClicked = false;
		     }

		     // Check which item that was clicked and take appropiate
		     // action.
		     itemNumber = getClickedItem(x, y);
		     if((itemNumber <= (character_->getAllItems().size() - 1)) && (!character_->getAllItems().empty()))
		     {
			    ItemAction(itemNumber, map);
		     }
	      }
       }

       // Check if lefthand has been clicked
       if(x > 28 && x < 94)
       {
	      if(y > 82 && y < 180)
	      {
		     if(leftHandClicked)
		     {
			    leftHandClicked = false;
		     }
		     else
		     {
			    if(!rightHandClicked)
			    {
				   leftHandClicked = true;
			    }
		     }
	      }
       }

       // Check if right hand is clicked
       if(x > 241 && x < 306)
       {
	      if(y > 82 && y < 180)
	      {
		     if(rightHandClicked)
		     {
			    rightHandClicked = false;
		     }
		     else
		     {
			    if(!leftHandClicked)
			    {
				   rightHandClicked = true;
			    }
		     }
	      }
       }
       return true;
}

/*
* Calculates which item that has been clicked in
* the inventory window.
*/
int InventoryWindow::getClickedItem(int x, int y)
{
       int row = 0;
       int column = 0;
       int itemnumber = 0;

       column = x/64;

       // Remove 269 pixels to get to square from the top.
       row = ((y - 269) / 64);

       itemnumber = column;

       if(row > 0)
       {
	      itemnumber += 5;
       }

       return itemnumber;
}

/*
* Takes action depending on state of inventory window.
* Either of the following can occur:
* 1. The user has clicked on one of the hands and the item that is
*    clicked will be equiped to that hand.
* 2. The user clicks an item and it is droped.
*/
void InventoryWindow::ItemAction(int num, class SDLMap *map)
{
       Item *tempitem;
       int tileX, tileY;

       if(rightHandClicked)
       {
	      if(character_->equipRightHand(character_->getItem(num)) != 0)
	      {
		     tempitem = character_->removeRightHandItem();
		     character_->equipRightHand(character_->getItem(num));
		     character_->add(tempitem);
	      }
	      character_->remove(character_->getItem(num));
	      rightHandClicked = false;
       }
       else if(leftHandClicked)
       {
	      if(character_->equipLeftHand(character_->getItem(num)) != 0)
	      {
		     tempitem = character_->removeLeftHandItem();
		     character_->equipLeftHand(character_->getItem(num));
		     character_->add(tempitem);
	      }
	      character_->remove(character_->getItem(num));
	      leftHandClicked = false;
       }
       else
       {
	      tempitem = character_->getItem(num);
	      character_->remove(character_->getItem(num));

	      tileX = character_->getX();
	      tileY = character_->getY();

	      /* Convert the characters cordinates to 
	         mapcoordinates. */
	      map->getTileXY(tileX, tileY);

	      /* Are we standing on an even tile? */
	      if(tileY%2 == 0)
	      {
		     /* Move one tile up-right from the characters position
			and start searching for a free tile to place the item
			on.
		     */
		     if(!map->containsItem(tileX, (tileY - 1)))
		     {
			    // Up-right
			    tempitem->setX(tileX);
			    tempitem->setY((tileY - 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem(tileX, (tileY + 1)))
		     {
			    // Down right
			    tempitem->setX(tileX);
			    tempitem->setY((tileY + 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem((tileX - 1), (tileY + 1)))
		     {
			    // Down left
			    tempitem->setX((tileX - 1));
			    tempitem->setY((tileY + 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem((tileX - 1), (tileY - 1)))
		     {
			    // Up-left
			    tempitem->setX((tileX - 1));
			    tempitem->setY((tileY - 1));
			    map->addItem(tempitem);
		     }
	      }
	      else
	      {
		     if(!map->containsItem((tileX + 1), (tileY - 1)))
		     {
			    // Up-right
			    tempitem->setX((tileX + 1));
			    tempitem->setY((tileY - 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem((tileX + 1), (tileY + 1)))
		     {
			    // Down right
			    tempitem->setX((tileX + 1));
			    tempitem->setY((tileY + 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem(tileX, (tileY + 1)))
		     {
			    // Down left
			    tempitem->setX(tileX);
			    tempitem->setY((tileY + 1));
			    map->addItem(tempitem);
		     }
		     else if(!map->containsItem(tileX, (tileY - 1)))
		     {
			    // Up-left
			    tempitem->setX(tileX);
			    tempitem->setY((tileY - 1));
			    map->addItem(tempitem);
		     }
	      }
       }
}

void InventoryWindow::drawItems()
{
	std::vector<class Item*> items;
	items = character_->getAllItems();
	int column;
	int row;

	column = 6;
	row = 269;

	//Draw item in lefthand
	if(character_->getLeftHand() != 0)
	{
	       drawHand(character_->getLeftHand()->getPicName(), 29, 82);
	}

	//Draw item in righthand
	if(character_->getRightHand() != 0)
	{
	       drawHand(character_->getRightHand()->getPicName(), 241, 82);
	}

	// Draw item in inventory-area
	for(int i=0; i < items.size(); i++)
	{
	       item_ = NULL;
	       item_ = IMG_Load(items[i]->getPicName().c_str());
	       if(item_ == NULL)
	       {
		      cout << "Could not load: " << items[i]->getPicName() << endl;
	       }
	       else
	       {
		      itemRect_.w = item_->w;
		      itemRect_.h = item_->h;
		      itemRect_.x = column;
		      itemRect_.y = row;
		      SDL_BlitSurface(item_, NULL, window_, &itemRect_);
		      column += 64;
		      if(column >= 320)
		      {
			     column = 0;
			     row += 64;
		      }
	       }
	       SDL_FreeSurface(item_);
	       item_ = NULL;
	}	       
}

void InventoryWindow::drawHand(std::string image, int x, int y)
{
       item_ = NULL;
       item_ = IMG_Load(image.c_str());
       if(item_ == NULL)
       {
	      cout << "Could not load: " << character_->getLeftHand()->getPicName() << endl;
       }
       itemRect_.w = item_->w;
       itemRect_.h = item_->h;
       itemRect_.x = x;
       itemRect_.y = y;
       SDL_BlitSurface(item_, NULL, window_, &itemRect_);
       SDL_FreeSurface(item_);

}